/**
 * 
 */
package edu.gatech.oad.yuno;

import java.util.Collections;
import java.util.HashMap;
import java.util.Date;
import java.util.List;
import java.util.ArrayList;

import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

/**
 * Model representing a to-do item
 * @author michael
 *
 */
public class Todo extends Model implements Comparable<Todo> {

	public Todo(long id) {
		if (Model.context == null) Model.context = YUNoDosApplication.getAppContext();
		this.id = id;
		this.table_name = "todos";
		this.data = new HashMap<String,Object>();
		this.load();
	}
	
	public Todo() {
		this(0);
	}

	public void validate() throws ValidationException {
		if (getName() == null || getName().equals("")) throw new ValidationException("Name cannot be blank.");
		if (data.get("user_id") == null || data.get("user_id").equals("")
				|| data.get("user_id").equals("0") || data.get("user_id").equals(0))
			throw new ValidationException("User cannot be empty.");
	}
	
	/**
	 * Find a Todo in the database by id
	 * @param id
	 * @return the Todo if found, null if not found
	 */
	public static Todo find(long id) {
		if (Model.context == null) Model.context = YUNoDosApplication.getAppContext();
		TodoListOpenHelper helper = new TodoListOpenHelper(Model.context);
		SQLiteDatabase db = helper.getReadableDatabase();
		String cols[] = {"id"};
		
		Cursor c = db.query("todos", cols, "id="+id, null, null, null, null, "1");
		if (c == null || c.getCount() < 1) {
			db.close();
			return null;
		}
		c.moveToFirst();
		long foundId = c.getLong(c.getColumnIndex("id"));
		
		db.close();
		return new Todo(foundId);
	}
	
	public static List<Todo> findAllByUser(long userId) {
		if (Model.context == null) Model.context = YUNoDosApplication.getAppContext();
		List<Todo> list = new ArrayList<Todo>();
		TodoListOpenHelper helper = new TodoListOpenHelper(Model.context);
		SQLiteDatabase db = helper.getReadableDatabase();
		String cols[] = {"id"};
		
		Cursor c = db.query("todos", cols, "user_id="+userId, null, null, null, null, null);
		if (c == null || c.getCount() < 1) {
			db.close();
			return list;
		}
		c.moveToFirst();
		list.add(new Todo(c.getLong(c.getColumnIndex("id"))));
		while (!c.isLast()) {
			c.moveToNext();
			list.add(new Todo(c.getLong(c.getColumnIndex("id"))));
		}
		Collections.sort(list);
		db.close();
		return list;
	}

	/**
	 * @return the name
	 */
	public String getName() {
		return (String) data.get("name");
	}

	/**
	 * @param name the name to set
	 */
	public void setName(String name) {
		data.put("name", name);
	}

	/**
	 * @return the description
	 */
	public String getDescription() {
		return (String) data.get("description");
	}

	/**
	 * @param description the description to set
	 */
	public void setDescription(String description) {
		data.put("description", description);
	}

	/**
	 * @return the priority
	 */
	public int getPriority() {
		int priority = getInt("priority");
		if (priority == -1) return 0;
		return priority;
	}

	/**
	 * @param priority the priority to set
	 */
	public void setPriority(int priority) {
		data.put("priority", Integer.toString(priority));
	}

	/**
	 * @return the dueDate
	 */
	public Date getDueDate() {
		long longDate = getLong("due_date");
		if (longDate < 1) return null;
		return new Date(longDate);
	}

	/**
	 * @param dueDate the dueDate to set
	 */
	public void setDueDate(Date dueDate) {
		if (dueDate!=null)
			data.put("due_date", Long.toString(dueDate.getTime()));
	}
	
	/**
	 * @param dueDate the dueDate to set
	 */
	public void setDueDate(long dueDate) {
		data.put("due_date", Long.toString(dueDate));
	}
	
	/**
	 * 
	 * @return the user
	 */
	public User getUser() {
		long id = getLong("user_id");
		if (id < 1) return null;
		return new User(id);
	}
	
	/**
	 * 
	 * @param user the user to set
	 */
	public void setUser(User user) {
		if (user == null) data.put("user_id", null);
		else data.put("user_id", Long.toString(user.getId()));
	}
	
	/**
	 * 
	 * @param userId the user id to set
	 */
	public void setUser(long userId) {
		data.put("user_id", Long.toString(userId));
	}
	
	/**
	 * 
	 * @return the location
	 */
	public Location getLocation() {
		long id = getLong("location_id");
		if (id < 1) return null;
		return new Location(id);
	}
	
	/**
	 * 
	 * @param location the location to set
	 */
	public void setLocation(Location location) {
		if (location == null) data.put("location_id", "0");
		else data.put("location_id", location.getId());
	}
	
	/**
	 * 
	 * @param locationId the location id to set
	 */
	public void setLocation(long locationId) {
		data.put("location_id", locationId);
	}
	
	/**
	 * 
	 * @return the category
	 */
	public Category getCategory() {
		long id = getLong("category_id");
		if (id < 1) return null;
		return new Category(id);
	}
	
	/**
	 * 
	 * @param category the category to set
	 */
	public void setCategory(Category category) {
		if (category == null) data.put("category_id", "0");
		else data.put("category_id", category.getId());
	}
	
	/**
	 * 
	 * @param categoryId the category id to set
	 */
	public void setCategory(long categoryId) {
		data.put("category_id", categoryId);
	}
	
	/**
	 * 
	 * @return whether this Todo is completed
	 */
	public boolean isCompleted() {
		return getBoolean("completed");
	}
	
	/**
	 * 
	 * @param completed
	 */
	public void setCompleted(boolean completed) {
		setBoolean("completed", completed);
	}
	
	/**
	 * 
	 * @return whether this Todo is recurring
	 */
	public boolean isRecurring() {
		return getBoolean("recurring");
	}
	
	/**
	 * 
	 * @param recurring
	 */
	public void setRecurring(boolean recurring) {
		setBoolean("recurring", recurring);
	}
	
	@Override
	public String toString() {
		return getName();
	}

	@Override
	public int compareTo(Todo another) {
		// TODO Auto-generated method stub
		if (getPriority() != another.getPriority()) {
			if (getPriority() > another.getPriority()) return -1;
			else return 1;
		}
		if (getDueDate() == null && another.getDueDate() != null) {
			return 1;
		} else if (getDueDate() != null && another.getDueDate() == null) {
			return -1;
		} else if (getDueDate() != null && another.getDueDate() != null) {
			if (!getDueDate().equals(another.getDueDate()))
				return -getDueDate().compareTo(another.getDueDate());
		}
		return getName().toLowerCase().compareTo(another.getName().toLowerCase());
	}
}
